﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Mall.Repository.Repository
{
    public class SqlBuilder
    {
        private static readonly List<string> S_listEnglishWords = new List<string>
    {
        "a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
        "k", "l", "m", "n", "o", "p", "q", "r", "s", "t",
        "u", "v", "w", "x", "y", "z"
    };

        private Dictionary<string, string> _dicTableName = new Dictionary<string, string>();

        private Queue<string> _queueEnglishWords = new Queue<string>(S_listEnglishWords);

        private StringBuilder _sqlBuilder;

        internal bool IsSingleTable { get; set; }

        internal List<string> SelectFields { get; set; }

        internal List<string> SelectFieldsAlias { get; set; }

        internal string SelectFieldsStr
        {
            get
            {
                string text = null;
                if (SelectFieldsAlias.Count > 0)
                {
                    for (int i = 0; i < SelectFields.Count; i++)
                    {
                        string text2 = SelectFields[i];
                        string text3 = SelectFieldsAlias[i];
                        text = ((!(text2.Split('.')[1] == text3)) ? (text + "," + text2 + " " + text3) : (text + "," + text2));
                    }

                    if (text.Length > 0 && text[0] == ',')
                    {
                        text = text.Remove(0, 1);
                    }
                }
                else
                {
                    text = string.Join(",", SelectFields);
                }

                return text;
            }
        }

        internal int Length => _sqlBuilder.Length;

        internal string Sql => ToString();

        internal Dictionary<string, object> DbParams { get; private set; }

        internal char this[int index] => _sqlBuilder[index];

        internal SqlBuilder()
        {
            DbParams = new Dictionary<string, object>();
            _sqlBuilder = new StringBuilder();
            SelectFields = new List<string>();
            SelectFieldsAlias = new List<string>();
        }

        public static SqlBuilder operator +(SqlBuilder sqlBuilder, string sql)
        {
            sqlBuilder._sqlBuilder.Append(sql);
            return sqlBuilder;
        }

        internal void Clear()
        {
            SelectFields.Clear();
            _sqlBuilder.Clear();
            DbParams.Clear();
            _dicTableName.Clear();
            _queueEnglishWords = new Queue<string>(S_listEnglishWords);
        }

        internal string AddDbParameter(object dbParamValue, bool allowAutoAppend = true)
        {
            string text = "";
            if (dbParamValue == null || dbParamValue == DBNull.Value)
            {
                if (allowAutoAppend)
                {
                    _sqlBuilder.Append(" null");
                }
            }
            else
            {
                text = "?param" + DbParams.Count;
                DbParams.Add(text, dbParamValue);
                if (allowAutoAppend)
                {
                    _sqlBuilder.Append(" " + text);
                }
            }

            return text;
        }

        internal bool SetTableAlias(string tableName)
        {
            if (!_dicTableName.Keys.Contains(tableName))
            {
                _dicTableName.Add(tableName, _queueEnglishWords.Dequeue());
                return true;
            }

            return false;
        }

        internal string GetTableAlias(string tableName)
        {
            if (!IsSingleTable && _dicTableName.Keys.Contains(tableName))
            {
                return _dicTableName[tableName];
            }

            return "";
        }

        public override string ToString()
        {
            return _sqlBuilder.ToString();
        }

        internal void Insert(int index, string value)
        {
            _sqlBuilder.Insert(index, value);
        }

        internal void AppendFormat(string format, object arg0)
        {
            _sqlBuilder.AppendFormat(format, arg0);
        }

        internal void AppendFormat(string format, object arg0, object arg1)
        {
            _sqlBuilder.AppendFormat(format, arg0, arg1);
        }

        internal void AppendFormat(string format, object arg0, object arg1, object arg2)
        {
            _sqlBuilder.AppendFormat(format, arg0, arg1, arg2);
        }

        internal void Remove(int startIndex, int length)
        {
            _sqlBuilder.Remove(startIndex, length);
        }
    }
}
